package com.hnhegui.backend.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 订单号生成器（基于Redis）
 */
@Component
public class OrderNoGenerator {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private static final String ORDER_NO_PREFIX = "order:no:";
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
    private static final int MAX_SEQUENCE = 999999; // 6位序列号的最大值

    // 用于测试的本地时间戳缓存
    private final List<String> localTimestamps = new ArrayList<>();
    // 用于测试的线程安全序列号
    private final AtomicInteger localSequence = new AtomicInteger(0);

    public OrderNoGenerator() {
        // 初始化100个随机时间戳缓存
        initializeLocalTimestamps();
    }

    /**
     * 初始化本地时间戳缓存
     * 创建范围在[now-100天, now]之间的100个随机时间戳
     */
    private void initializeLocalTimestamps() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime startDate = now.minusDays(100);

        for (int i = 0; i < 100; i++) {
            // 在范围[startDate, now]内生成随机时间
            long randomSeconds = ThreadLocalRandom.current()
                    .nextLong(startDate.toEpochSecond(java.time.ZoneOffset.UTC),
                            now.toEpochSecond(java.time.ZoneOffset.UTC));
            LocalDateTime randomDate = LocalDateTime.ofEpochSecond(randomSeconds, 0, java.time.ZoneOffset.UTC);
            localTimestamps.add(randomDate.format(DATE_FORMATTER));
        }
    }

    /**
     * 生成订单号（用于生产环境，基于Redis）
     * 格式：yyyyMMddHHmmss + 6位自增序列号
     *
     * @return 订单号
     */
    public String generateOrderNo() {
        // 获取当前时间戳
        String timestamp = LocalDateTime.now().format(DATE_FORMATTER);

        // 构建Redis Key
        String redisKey = ORDER_NO_PREFIX + timestamp;

        // 原子递增获取序列号
        Long sequence = redisTemplate.opsForValue().increment(redisKey);

        // 设置Key过期时间为1天
//        redisTemplate.expire(redisKey, 1, TimeUnit.DAYS);

        // 将序列号补齐为6位
        String sequenceStr = String.format("%06d", sequence);

        // 拼接订单号
        return timestamp + sequenceStr;
    }

    /**
     * 生成订单号（用于测试环境，不使用Redis）
     * 使用本地缓存的时间戳和线程安全的递增序列
     *
     * @return 订单号
     */
    public String generateOrderNoForTest() {
        // 从本地缓存中随机选择一个时间戳
        int randomIndex = ThreadLocalRandom.current().nextInt(localTimestamps.size());
        String timestamp = localTimestamps.get(randomIndex);

        // 原子递增获取序列号（线程安全）
        // 使用取模运算确保序列号不超过6位
        int sequence = localSequence.incrementAndGet() % (MAX_SEQUENCE + 1);

        // 将序列号补齐为6位
        String sequenceStr = String.format("%06d", sequence);

        // 拼接订单号
        return timestamp + sequenceStr;
    }
}